package jmine.tec.utils;

import java.io.Serializable;
import java.util.Map;

/**
 * Uma {@link Tuple} modificavel.
 * 
 * @author takeshi.fukushima
 * @param <H>
 * @param <T>
 */
public class MutableTuple<H, T> extends AbstractTuple<H, T> implements Serializable, Cloneable, Map.Entry<H, T> {

    private volatile H head;

    private volatile T tail;

    /**
     * C'tor
     * 
     * @param head o primeiro elemento
     * @param tail o segundo elemento
     */
    public MutableTuple(H head, T tail) {
        super();
        this.head = head;
        this.tail = tail;
    }

    /**
     * C'tor
     */
    public MutableTuple() {
    }

    /**
     * @return the head
     */
    public H getHead() {
        return this.head;
    }

    /**
     * @param head the head to set
     */
    public void setHead(H head) {
        this.head = head;
    }

    /**
     * @return the tail
     */
    public T getTail() {
        return this.tail;
    }

    /**
     * @param tail the tail to set
     */
    public void setTail(T tail) {
        this.tail = tail;
    }

    /**
     * Constroi uma nova tupla
     * 
     * @param <H> o tipo do primeiro elemento
     * @param <T> o tipo do segundo elemento
     * @return {@link Tuple}
     */
    public static <H, T> Tuple<H, T> newTuple() {
        return new MutableTuple<H, T>();
    }

    /**
     * Constroi uma nova tupla
     * 
     * @param <H> o tipo do primeiro elemento
     * @param <T> o tipo do segundo elemento
     * @param head o primeiro elemento
     * @param tail o segundo elemento
     * @return {@link Tuple}
     */
    public static <H, T> MutableTuple<H, T> newTuple(H head, T tail) {
        return new MutableTuple<H, T>(head, tail);
    }

    /**
     * Este metodo nao usa o caminho rapido para clonar objetos. Ao inves disso, invoca o construtor normal. {@inheritDoc}
     */
    public Tuple<H, T> copy() {
        return newTuple(this.head, this.tail);
    }

    /**
     * {@inheritDoc}
     */
    public Tuple<T, H> invert() {
        return newTuple(this.tail, this.head);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Object clone() {
        return super.clone();
    }

    /**
     * {@inheritDoc}
     */
    public H getKey() {
        return getHead();
    }

    /**
     * {@inheritDoc}
     */
    public T getValue() {
        return getTail();
    }

    /**
     * {@inheritDoc}
     */
    public T setValue(T value) {
        T old = this.tail;
        this.tail = value;
        return old;
    }

}
